package com.thoughtorigin.reflect {
import flash.utils.Dictionary;

public class DescribeMetaReader implements MetaReader {

    private var _xml: XML;
    private var _metaData: DescribeObjectMetaData;

    public function populateMetaData(describe:XML, onComplete:Function): void {
        _xml = describe;
        _metaData = new DescribeObjectMetaData();
        _metaData.className = _xml.@name.toString();
        _metaData.classMetaData = populateClassMetaData();
        _metaData.functionMetaData = populateFunctionMetaData();
        _metaData.propertyMetaData = populatePropertyMetaData();

        onComplete.call(this);
        _xml = null;
    }

    private function populatePropertyMetaData():Dictionary {
        var retVal: Dictionary = new Dictionary();
        for each(var xml: XML in _xml.factory.accessor) {
            var propArray:Array = [];
            for each(var metaXML: XML in xml.metadata) {
                propArray.push(new PropertyMetaDataItem(metaXML.@name, gatherMetaArgs(metaXML),xml.@name, getAccessType(xml)));
            }
            if(propArray.length > 0) {
                retVal[xml.@name.toString()] = propArray;
            }
        }
        return retVal;
    }

    private function getAccessType(xml: XML): PropertyAccess {
        if(xml.@access == "readonly"){
            return PropertyAccess.READ_ONLY;
        }else if(xml.@access == "writeonly"){
            return PropertyAccess.WRITE_ONLY;
        }else if(xml.@access == "readwrite"){
            return PropertyAccess.READ_WRITE;
        }
        throw new Error("Property access undefined. For property:" + xml.@name);
    }

    private function populateFunctionMetaData():Dictionary {
        var retVal: Dictionary = new Dictionary();
        for each(var xml: XML in _xml.factory.method) {
            var funcArray: Array = [];
            for each(var metaXML: XML in xml.metadata) {
                funcArray.push(new FunctionMetaDataItem(metaXML.@name, gatherMetaArgs(metaXML),xml.@name.toString()));
            }
            if(funcArray.length > 0) {
                retVal[xml.@name.toString()] = funcArray;
            }
        }

        return retVal;
    }

    private function gatherMetaArgs(xml: XML): Array {
        var args: Array = [];
        for each(var arg: XML in xml.arg) {
            var metaArg: MetaArg = new MetaArg(arg.@key, arg.@value);
            args.push(metaArg);
        }
        return args;
    }

    private function populateClassMetaData(): Dictionary {
        var retVal: Dictionary = new Dictionary();

        for each(var xml: XML in _xml.factory.metadata) {
            retVal[xml.@name.toString()] = new ConstructorMetaData(xml.@name, gatherMetaArgs(xml), _metaData.className);
        }

        return retVal;
    }

    public function get classMetaData(): ObjectMetaData {
        return _metaData;        
    }
}
}